package com.cskaoyan.market.service;

import com.cskaoyan.market.bo.MarketGoodsBo;
import com.cskaoyan.market.db.domain.*;
import com.cskaoyan.market.db.mapper.*;
import com.cskaoyan.market.util.MybatisUtils;
import com.cskaoyan.market.vo.CatAndBrandVo;
import com.cskaoyan.market.vo.MarketGoodsVo;
import com.cskaoyan.market.vo.MarketGoodsVoRows;
import com.cskaoyan.market.vo.TimeConUtil;
import com.github.pagehelper.PageHelper;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.SqlSession;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;

public class MarketGoodsServiceImpl implements MarketGoodsService {


    @Override
    public List<MarketGoods> list(Integer page, Integer limit, String goodsSn, String name, String sort, String order, String goodsId) {
        //使用mybatis去数据库中查询数据
        SqlSession session = MybatisUtils.getSession();
        MarketGoodsMapper mapper = session.getMapper(MarketGoodsMapper.class);
        MarketGoodsExample marketGoodsExample = new MarketGoodsExample();
        marketGoodsExample.setOrderByClause(sort + " " + order);
        MarketGoodsExample.Criteria criteria = marketGoodsExample.createCriteria();
        if (!StringUtils.isEmpty(goodsId)) {
            criteria.andIdEqualTo(Integer.parseInt(goodsId));
        }
        if (!StringUtils.isEmpty(goodsSn)) {
            criteria.andGoodsSnLike("%" + goodsSn + "%");
        }
        if (!StringUtils.isEmpty(name)) {
            criteria.andNameLike("%" + name + "%");
        }
        PageHelper.startPage(page, limit);
        List<MarketGoods> marketGoodsList = mapper.selectByExample(marketGoodsExample);
        session.commit();
        session.close();
        return marketGoodsList;
    }

    @Override
    public Map<String, Object> catAndBrand() {
        //查询category和brand两张表
        SqlSession session = MybatisUtils.getSession();
        MarketCategoryMapper categoryMapper = session.getMapper(MarketCategoryMapper.class);
        MarketBrandMapper brandMapper = session.getMapper(MarketBrandMapper.class);
        List<MarketCategory> categories = categoryMapper.selectByExample(new MarketCategoryExample());
        List<MarketBrand> brands = brandMapper.selectByExample(new MarketBrandExample());
        session.commit();
        session.close();
        //保存返回信息
        Map<String, Object> result = new HashMap<>();
        List<CatAndBrandVo> brandList = new ArrayList<>();
        List<CatAndBrandVo> categoryList = new ArrayList<>();
        //categoryList的数据同样需要通过pid进行分组，与region中的方法类似，通过map分组，key为pid，value为有当前pid的所有对象
        Map<Integer, List<MarketCategory>> categoriesByPid = groupByPid(categories);
        //先获取一级类目
        List<MarketCategory> l1Categories = categoriesByPid.get(0);
        for (MarketCategory l1 : l1Categories) {
            List<CatAndBrandVo> children = new ArrayList<>();
            CatAndBrandVo l1Vo = new CatAndBrandVo(l1.getName(), l1.getId(), children);
            categoryList.add(l1Vo);
            List<MarketCategory> l2Categories = categoriesByPid.get(l1.getId());
            if (l2Categories != null) {
                for (MarketCategory l2 : l2Categories) {
                    children.add(new CatAndBrandVo(l2.getName(), l2.getId(), null));
                }
            }
        }
        for (MarketBrand brand : brands) {
            brandList.add(new CatAndBrandVo(brand.getName(), brand.getId(), null));
        }
        result.put("brandList", brandList);
        result.put("categoryList", categoryList);
        return result;
    }

    @Override
    public void create(MarketGoods goods, List<MarketGoodsProduct> products, List<MarketGoodsSpecification> specifications, List<MarketGoodsAttribute> attributes) {
        SqlSession session = MybatisUtils.getSession();
        MarketGoodsMapper marketGoodsMapper = session.getMapper(MarketGoodsMapper.class);
        MarketGoodsSpecificationMapper specificationMapper = session.getMapper(MarketGoodsSpecificationMapper.class);
        MarketGoodsProductMapper productMapper = session.getMapper(MarketGoodsProductMapper.class);
        MarketGoodsAttributeMapper attributeMapper = session.getMapper(MarketGoodsAttributeMapper.class);

        //首先插入goods表
        //零售价格---所有规格中较低的一个价格
        //获取所有的货品价格，取一个较低的价格
        //在外部设置一个较大的变量，如果遇到小值，则更新；取index=0下标的；如果后续遇到小值，也是更新
        BigDecimal price = products.get(0).getPrice();
        for (int i = 1; i < products.size(); i++) {
            //如果后续出现了一个更小的值，则更新price的值
            BigDecimal decimal = products.get(i).getPrice();
            if (price.compareTo(decimal) == 1) {
                //表示price 大于decimal的值，出现更小值，则把更小的值赋值给price
                price = decimal;
            }
        }
        goods.setRetailPrice(price);
        goods.setAddTime(LocalDateTime.now());
        goods.setUpdateTime(LocalDateTime.now());
        goods.setDeleted(false);
        //最终要保障事务
        try {
            marketGoodsMapper.insertSelective(goods);
            Integer id = goods.getId();
            //插入规格
            //对于另外三张表来说，需要goods的编号，怎么获取goods的编号？？？？？goods.getId即可
            for (MarketGoodsSpecification sp : specifications) {
                sp.setGoodsId(id);
                sp.setAddTime(LocalDateTime.now());
                sp.setUpdateTime(LocalDateTime.now());
                sp.setDeleted(false);
                specificationMapper.insertSelective(sp);
            }
            for (MarketGoodsProduct product : products) {
                product.setGoodsId(id);
                product.setAddTime(LocalDateTime.now());
                product.setUpdateTime(LocalDateTime.now());
                product.setDeleted(false);
                productMapper.insertSelective(product);
            }
            for (MarketGoodsAttribute attribute : attributes) {
                attribute.setGoodsId(id);
                attribute.setAddTime(LocalDateTime.now());
                attribute.setUpdateTime(LocalDateTime.now());
                attribute.setDeleted(false);
                attributeMapper.insertSelective(attribute);
            }
            session.commit();
        } catch (Exception e) {
            session.rollback();
        } finally {
            session.close();
        }
    }

    @Override
    public void update(MarketGoods goods, List<MarketGoodsProduct> products, List<MarketGoodsSpecification> specifications, List<MarketGoodsAttribute> attributes) {
        SqlSession session = MybatisUtils.getSession();
        MarketGoodsMapper goodsMapper = session.getMapper(MarketGoodsMapper.class);
        MarketGoodsProductMapper productMapper = session.getMapper(MarketGoodsProductMapper.class);
        MarketGoodsSpecificationMapper specificationMapper = session.getMapper(MarketGoodsSpecificationMapper.class);
        MarketGoodsAttributeMapper attributeMapper = session.getMapper(MarketGoodsAttributeMapper.class);

        try {
            //每更新一条都设置更新时间，如果之前为空，后来添加了，则插入
            goods.setUpdateTime(LocalDateTime.now());
            Integer id = goods.getId();
            goodsMapper.updateByPrimaryKeySelective(goods);
            for (MarketGoodsProduct product : products) {
                product.setUpdateTime(LocalDateTime.now());
                product.setDeleted(false);
                productMapper.updateByPrimaryKeySelective(product);
            }
            for (MarketGoodsSpecification specification : specifications) {
                specification.setUpdateTime(LocalDateTime.now());
                specification.setDeleted(false);
                specificationMapper.updateByPrimaryKeySelective(specification);
            }
            //attribute可能有新添加的项，如果原来未创建过，则改为新增
            for (MarketGoodsAttribute attribute : attributes) {
                attribute.setUpdateTime(LocalDateTime.now());
                //判断是否是新增的条目，是则插入，不是则更新时间
                MarketGoodsAttribute marketGoodsAttribute = attributeMapper.selectByPrimaryKey(attribute.getId());
                if (marketGoodsAttribute==null){
                    attribute.setAddTime(LocalDateTime.now());
                    attribute.setGoodsId(id);
                    attribute.setDeleted(false);
                    attributeMapper.insert(attribute);
                }else {
                    attributeMapper.updateByPrimaryKey(attribute);
                }

            }
            session.commit();
        } catch (Exception e) {
            session.rollback();
            throw new RuntimeException(e);
        } finally {
            session.close();
        }
    }

    @Override
    public Map<String, Object> detail(Integer goodsId) {
        MarketGoodsBo marketGoodsBo = new MarketGoodsBo();
        SqlSession session = MybatisUtils.getSession();
        MarketGoodsMapper goodsMapper = session.getMapper(MarketGoodsMapper.class);
        MarketCategoryMapper categoryMapper = session.getMapper(MarketCategoryMapper.class);
        MarketGoodsProductMapper productMapper = session.getMapper(MarketGoodsProductMapper.class);
        MarketGoodsSpecificationMapper specificationMapper = session.getMapper(MarketGoodsSpecificationMapper.class);
        MarketGoodsAttributeMapper attributeMapper = session.getMapper(MarketGoodsAttributeMapper.class);
        Map<String, Object> result = new HashMap<>();
        //goods
        MarketGoodsExample goodsExample = new MarketGoodsExample();
        MarketGoodsExample.Criteria goodsExampleCriteria = goodsExample.createCriteria();
        goodsExampleCriteria.andIdEqualTo(goodsId);
        MarketGoods marketGoods = goodsMapper.selectOneByExampleWithBLOBs(goodsExample);
        marketGoodsBo.setGoods(marketGoods);
        //categoryIds
        List<Integer> categoryIds = null;
        Integer categoryId = marketGoods.getCategoryId();
        MarketCategory marketCategory = categoryMapper.selectByPrimaryKey(categoryId);
        if (marketCategory != null) {
            categoryIds = Arrays.asList(marketCategory.getPid(), categoryId);
        }
        //productList
        MarketGoodsProductExample marketGoodsProductExample = new MarketGoodsProductExample();
        MarketGoodsProductExample.Criteria criteria = marketGoodsProductExample.createCriteria();
        criteria.andGoodsIdEqualTo(goodsId);
        List<MarketGoodsProduct> productList = productMapper.selectByExample(marketGoodsProductExample);
        //specificationList
        MarketGoodsSpecificationExample marketGoodsSpecificationExample = new MarketGoodsSpecificationExample();
        MarketGoodsSpecificationExample.Criteria specificationExampleCriteria = marketGoodsSpecificationExample.createCriteria();
        specificationExampleCriteria.andGoodsIdEqualTo(goodsId);
        List<MarketGoodsSpecification> specificationList = specificationMapper.selectByExample(marketGoodsSpecificationExample);
        //attributeList
        MarketGoodsAttributeExample marketGoodsAttributeExample = new MarketGoodsAttributeExample();
        MarketGoodsAttributeExample.Criteria attributeExampleCriteria = marketGoodsAttributeExample.createCriteria();
        attributeExampleCriteria.andGoodsIdEqualTo(goodsId);
        List<MarketGoodsAttribute> attributeList = attributeMapper.selectByExample(marketGoodsAttributeExample);
        result.put("goods", marketGoods);
        result.put("categoryIds", categoryIds);
        result.put("attributes", attributeList);
        result.put("products", productList);
        result.put("specifications", specificationList);
        session.commit();
        session.close();
        return result;
    }

    @Override
    public void delete(MarketGoods goods) {
        SqlSession session = MybatisUtils.getSession();
        MarketGoodsMapper goodsMapper = session.getMapper(MarketGoodsMapper.class);
        goodsMapper.deleteByPrimaryKey(goods.getId());
        session.commit();
        session.close();
    }


    private Map<Integer, List<MarketCategory>> groupByPid(List<MarketCategory> categories) {
        Map<Integer, List<MarketCategory>> result = new HashMap<>();
        for (MarketCategory category : categories) {
            Integer pid = category.getPid();
            List<MarketCategory> marketCategoryList = result.get(pid);
            if (marketCategoryList == null) {
                marketCategoryList = new ArrayList<>();
            }
            marketCategoryList.add(category);
            result.put(pid, marketCategoryList);
        }
        return result;
    }
    @Override
    public MarketGoodsVo getGoods() {
        SqlSession sqlSession= MybatisUtils.getSession();
        MarketOrderGoodsMapper marketOrderGoodsMapper = sqlSession.getMapper(MarketOrderGoodsMapper.class);
        List<MarketOrderGoods> marketOrderGoods = marketOrderGoodsMapper.selectByExample(new MarketOrderGoodsExample());
        sqlSession.commit();
        sqlSession.close();
        Map<String,List<MarketOrderGoods>> goodsGroupByTime=goodsGroupByTime(marketOrderGoods);
        List<MarketGoodsVoRows> rows1= new ArrayList<>();
        for (Map.Entry<String, List<MarketOrderGoods>> stringListEntry : goodsGroupByTime.entrySet()) {
            MarketGoodsVoRows row=getRows(stringListEntry.getKey(),stringListEntry.getValue());
            rows1.add(row);
        }
        MarketGoodsVo marketGoodsVo=new MarketGoodsVo();
        marketGoodsVo.setRows(rows1);
        String[] s1=new String[]{"day","orders","products","amount"};
        marketGoodsVo.setColumns(s1);
        return marketGoodsVo;
    }

    private MarketGoodsVoRows getRows(String key, List<MarketOrderGoods> value) {
        MarketGoodsVoRows r1=new MarketGoodsVoRows();
        r1.setDay(key);
        List<Integer> numList=new ArrayList<>();
        List<BigDecimal> priceList=new ArrayList<>();
        Set<Integer> orders1=new HashSet<>();
        for (MarketOrderGoods marketOrderGoods : value) {
            int  number = marketOrderGoods.getNumber();
            BigDecimal price = marketOrderGoods.getPrice();
            Integer orderId = marketOrderGoods.getOrderId();
            BigDecimal value1 = BigDecimal.valueOf(number);
            BigDecimal multiply = price.multiply(value1);
            numList.add(number);
            priceList.add(multiply);
            orders1.add(orderId);
        }
        int size = orders1.size();
        Integer sum = numList.stream().reduce(Integer::sum).orElse(0);
        BigDecimal sum1=priceList.stream().reduce(BigDecimal.ZERO,BigDecimal::add);
        r1.setOrders(size);
        r1.setProducts(sum);
        r1.setAmount(sum1);
        return r1;
    }

    private Map<String, List<MarketOrderGoods>> goodsGroupByTime(List<MarketOrderGoods> marketOrderGoods) {
        Map<String,List<MarketOrderGoods>> listMap=new TreeMap<>();
        for (MarketOrderGoods marketOrderGood : marketOrderGoods) {
            LocalDateTime updateTime = marketOrderGood.getUpdateTime();
            if(updateTime!=null){
                String timeCon1 = TimeConUtil.TimeCon(updateTime);
                List<MarketOrderGoods> list=listMap.get(timeCon1);
                if(list==null){
                    list=new ArrayList<>();
                }
                list.add(marketOrderGood);
                listMap.put(timeCon1,list);
            }
        }
        return listMap;
    }

}

